package logger

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
	"path/filepath"
	"time"
)

var zapLog *zap.Logger

/**
 * filePath		日志文件路径
 *	//log.GetLogger().Info("启动中")
 *	//log.GetLogger().Error("123")
 */
func LogInit(filePath string) {
	dir := filepath.Dir(filePath)
	_, err := os.Stat(dir)
	if err != nil {
		os.MkdirAll(dir, 0777)
		if err != nil {
			panic(err)
		}
	}
	Encoder := GetEncoder()
	WriteSyncer := GetWriteSyncer(filePath)
	LevelEnabler := GetLevelEnabler()
	ConsoleEncoder := GetConsoleEncoder()

	Core := zapcore.NewCore(Encoder, WriteSyncer, LevelEnabler)
	newCore := zapcore.NewTee(
		Core,
		zapcore.NewCore(ConsoleEncoder, zapcore.Lock(os.Stdout), zapcore.DebugLevel), // 写入控制台
	)
	logger := zap.New(newCore, zap.AddCaller())
	zap.ReplaceGlobals(logger)
	zapLog = logger
}

func LogInitV2(filePath string, itemSizeMb int, maxAge int, maxBackups int) {
	dir := filepath.Dir(filePath)
	_, err := os.Stat(dir)
	if err != nil {
		os.MkdirAll(dir, 0777)
		if err != nil {
			panic(err)
		}
	}
	Encoder := GetEncoder()
	WriteSyncer := GetWriteSyncerV2(filePath, itemSizeMb, maxAge, maxBackups)
	LevelEnabler := GetLevelEnabler()
	ConsoleEncoder := GetConsoleEncoder()

	Core := zapcore.NewCore(Encoder, WriteSyncer, LevelEnabler)
	newCore := zapcore.NewTee(
		Core,
		zapcore.NewCore(ConsoleEncoder, zapcore.Lock(os.Stdout), zapcore.DebugLevel), // 写入控制台
	)
	logger := zap.New(newCore, zap.AddCaller())
	zap.ReplaceGlobals(logger)
	zapLog = logger
}

func GetWriteSyncerV2(fileName string, itemSizeMb int, maxAge int, maxBackups int) zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   fileName,
		MaxSize:    itemSizeMb, // mb
		MaxBackups: maxBackups,
		MaxAge:     maxAge,
	}
	return zapcore.AddSync(lumberJackLogger)
}

func GetEncoder() zapcore.Encoder {
	return zapcore.NewConsoleEncoder(
		zapcore.EncoderConfig{
			TimeKey:        "ts",
			LevelKey:       "level",
			NameKey:        "logger",
			CallerKey:      "caller_line",
			FunctionKey:    zapcore.OmitKey,
			MessageKey:     "msg",
			StacktraceKey:  "stacktrace",
			LineEnding:     "\n",
			EncodeLevel:    cEncodeLevel,
			EncodeTime:     cEncodeTime,
			EncodeDuration: zapcore.SecondsDurationEncoder,
			EncodeCaller:   cEncodeCaller,
		})
}

// GetConsoleEncoder 输出日志到控制台
func GetConsoleEncoder() zapcore.Encoder {
	return zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
}

func GetLevelEnabler() zapcore.Level {
	return zapcore.InfoLevel // 只会打印出info及其以上级别的日志
}

// GetWriteSyncer 自定义的WriteSyncer
func GetWriteSyncer(fileName string) zapcore.WriteSyncer {
	lumberJackLogger := &lumberjack.Logger{
		Filename:   fileName,
		MaxSize:    10, // mb
		MaxBackups: 10,
		MaxAge:     30,
	}
	return zapcore.AddSync(lumberJackLogger)
}

// cEncodeLevel 自定义日志级别显示
func cEncodeLevel(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString("[" + level.CapitalString() + "]")
}

// cEncodeTime 自定义时间格式显示
func cEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString("[" + t.Format("2006-01-02 15:04:05") + "]")
}

// cEncodeCaller 自定义行号显示
func cEncodeCaller(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString("[" + caller.TrimmedPath() + "]")
}

func GetLogger() *zap.Logger {
	return zapLog
}
